package com.suse.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.util.RandomUtil;
import com.suse.common.util.core.UUIDUtil;
import com.suse.constant.RedisConstant;
import com.suse.model.vo.UserVo;
import com.suse.result.Result;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.suse.model.param.LoginParam;
import com.suse.entity.User;
import com.suse.mapper.UserMapper;
import com.suse.service.UserService;
import com.suse.common.util.core.StringUtil;
import com.suse.common.util.regex.RegexUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.concurrent.TimeUnit;

import static com.suse.constant.UserConstant.*;
import static com.suse.result.ResultEnum.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 虎哥
 * @since 2021-12-22
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    private final StringRedisTemplate redisTemplate;

    public UserServiceImpl(StringRedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Override
    public Result sendCode(String phone) {
        // 1.判断手机号是否合法
        if (RegexUtil.isNotPhone(phone)) {
            // 2.不合法，返回错误信息
            return Result.error(RESULT_PHONE_ILLEGAL);
        }
        // 3.合法，生成验证码
        String code = RandomUtil.randomNumbers(USER_LOGIN_CODE_LENGTH);
        // 4.保存验证码到 redis
        redisTemplate.opsForValue().set(RedisConstant.LOGIN_CODE_PREFIX + phone,code, RedisConstant.LOGIN_CODE_TTL, TimeUnit.MINUTES);
        //TODO 5.发送验证码 需要调用第三方平台 这里只是打印一下不做实现
        log.info("发送验证码成功！验证码：{}",code);
        // 6.返回成功信息
        return Result.success();
    }

    @Override
    public Result login(LoginParam loginParam) {
        // 1.判断手机号是否合法
        String phone = loginParam.getPhone();
        if (RegexUtil.isNotPhone(phone)) {
            // 2.不合法，返回错误信息
            return Result.error(RESULT_PHONE_ILLEGAL);
        }
        // 3.合法，从缓存中获取验证码
        String redisCode = redisTemplate.opsForValue().get(RedisConstant.LOGIN_CODE_PREFIX + phone);
        // 4.判断验证码是否一致
        String code = loginParam.getCode();
        if (StringUtil.isNotEquals(redisCode,code)) {
            // 5.不一致，返回错误信息
            return Result.error(RESULT_CODE_ERROR);
        }
        // 6.一致，根据手机号从数据库中查询用户
        User user = lambdaQuery().eq(User::getPhone,phone).one();
        // 7.判断用户是否存在
        if (user == null) {
            // 8.不存在，创建新用户
            user = createNewUserWithPhone(phone);
            // 9.保存新用户到 mysql 中
            save(user);
        }
        // 10.存在，保存用户信息到 redis 中
        String token = UUIDUtil.generateUUID();
        UserVo userVo = BeanUtil.copyProperties(user, UserVo.class);
        String userKey = RedisConstant.LOGIN_USER_PREFIX + token;
        // 11. hash存储用户信息
        redisTemplate.opsForHash().putAll(userKey,BeanUtil.beanToMap(
                userVo,
                new HashMap<>(),
                CopyOptions.create().ignoreNullValue().setFieldValueEditor((fieldName, fieldValue) -> fieldValue.toString())
        ));
        redisTemplate.expire(userKey, RedisConstant.LOGIN_USER_TTL,TimeUnit.MINUTES);
        // 12.返回token
        return Result.success(token);
    }

    /**
     * 创建新用户
     * @param phone 手机号
     * @return 用户
     */
    private User createNewUserWithPhone(String phone) {
        User user = new User();
        user.setPhone(phone);
        user.setNickName(USER_NICKNAME_PREFIX + RandomUtil.randomString(USER_NICKNAME_SUFFIX_LENGTH));
        return user;
    }

}
